package com.jamiexu.cn.chatwith.socket;


import com.jamiexu.cn.chatwith.Imp.ISocketProtocol;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class SocketProtocol implements ISocketProtocol {


    //协议指令
    public static final String OP_MESSAGE_CLIENT_SEND = "OP_MESSAGE_CLIENT_SEND";//客户端发送信息

    public static final String OP_MESSAGE_SERVER_SEND = "OP_MESSAGE_SERVER_SEND";//服务器发送信息

    public static final String OP_CONNECTION_CLIENT_CONNECT = "OP_CONNECTION_CLIENT_CONNECT";//客户端请求连接

    public static final String OP_CONNECTION_SERVER_CONNECT = "OP_CONNECTION_SERVER_CONNECT";//服务端发送连接成功

    public static final String OP_CONNECTION_CLIENT_DISCONNECT = "OP_CONNECTION_CLIENT_DISCONNECT";//客户端取消连接

    public static final String OP_CONNECTION_SERVER_DISCONNECT = "OP_CONNECTION_SERVER_DISCONNECT";//服务端发送关闭连接

    public static final String OP_CONNECTION_CLIENT_STATUS = "OP_CONNECTION_CLIENT_STATUS";//客户端心跳包

    private Socket socket;

    public SocketProtocol(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void sendData(String opString, String... datas) throws IOException {
        DataOutputStream dataOutputStream = new DataOutputStream(this.socket.getOutputStream());
        int totalLen = 4 * 2;
        byte[] senderBytes = null;
        byte[] messageBytes = null;
        byte[] opBytes = opString.getBytes(StandardCharsets.UTF_8);
        totalLen += opBytes.length;

        if (datas.length > 0) {
            senderBytes = datas[0].getBytes(StandardCharsets.UTF_8);
            totalLen += 4 + senderBytes.length;
        }

        if (datas.length > 1) {
            messageBytes = datas[1].getBytes(StandardCharsets.UTF_8);
            totalLen += 4 + messageBytes.length;
        }

        if (senderBytes != null && messageBytes != null)
            totalLen += 4;

        dataOutputStream.writeInt(totalLen);
        dataOutputStream.writeInt(opBytes.length);
        dataOutputStream.write(opBytes);

        if (senderBytes != null) {
            dataOutputStream.writeInt(senderBytes.length);
            dataOutputStream.write(senderBytes);
        }

        if (messageBytes != null) {
            dataOutputStream.writeInt(messageBytes.length);
            dataOutputStream.write(messageBytes);
        }

        if (senderBytes != null && messageBytes != null)
            dataOutputStream.writeInt((opBytes.length + senderBytes.length + messageBytes.length) % 3);


        dataOutputStream.flush();


    }

    @Override
    public byte[] acceptData() throws IOException {
        DataInputStream dataInputStream = new DataInputStream(this.socket.getInputStream());
        int dataLen = dataInputStream.readInt();
        byte[] data = new byte[dataLen - 4];
        dataInputStream.readFully(data);
        return data;
    }

    @Override
    public Object[] getBlock() throws IOException {

        Object[] objects = new Object[4];
        byte[] data = this.acceptData();
        int dataLen = data.length;
        int totalLen = 0;

        DataInputStream dataInputStream = new DataInputStream(new ByteArrayInputStream(data));
        int opLen = dataInputStream.readInt();

        byte[] opBytes = new byte[opLen];
        dataInputStream.readFully(opBytes);
        String op = new String(opBytes, StandardCharsets.UTF_8);
        objects[0] = op;
        totalLen += 4 + opLen;

        if (dataLen > totalLen) {
            int senderLen = dataInputStream.readInt();
            byte[] senderBytes = new byte[senderLen];
            dataInputStream.readFully(senderBytes);
            String sender = new String(senderBytes, StandardCharsets.UTF_8);
            objects[1] = sender;
            totalLen += 4 + senderLen;
        }

        if (dataLen > totalLen) {
            int messageLen = dataInputStream.readInt();
            byte[] messageBytes = new byte[messageLen];
            dataInputStream.readFully(messageBytes);
            String message = new String(messageBytes, StandardCharsets.UTF_8);
            objects[2] = message;
            totalLen += 4 + messageLen;
        }

        if (dataLen > totalLen) {
            int checkCode = dataInputStream.readInt();
            objects[3] = checkCode;
            totalLen += 4;
        }

        if (dataLen == totalLen) {
            return objects;
        } else
            return null;
    }
}
